﻿#include <iostream>
#include <fstream>
#include <io.h>
#include <direct.h>

#include "BPAInterface.h"
#include "PowerBalanceInZone.h"
#include "DatBridging.h"
#include <BPAFilesIO.h>

#include "OPF/ToExecuteMinPf.h"
#include "OPF/MinPowerBalanceInZone.h"
#include "OPF/MinPowerFlowRes.h"

#include "ParCheck/BandBQCheck.h"
#include "ParCheck/CheckBpaConnAndBalan.h"
#include "ParCheck/LineParCheck.h"
#include "ParCheck/TranParCheck.h"
#include "ParCheck/LineLDParCheck.h"
#include "ParCheck/ParCheckDb2Dat.h"
#include "OPF/PowerFlowAutoAdjustment.h"
#include "OPF/ZoneAutoAdjustment.h"

using namespace JGG;

STS_MSG BPAInitialize(const char* Database)
{
    BPA::BPAFilesIO::WriteConfiguration w1;
    w1.WriteConfigToDataBase(Database);
    w1.InitializeDataBase(Database);
    w1.UIConfigWriteToDataBase(Database);
    //w1.BpaPinJieCfg(Database);
    //w1.CaseIDFileUserChoose(Database);
    //w1.TypicalSWICfg(Database);
    return STS_SUCCEED;
}

STS_MSG BPAAnalysis(const char* FilePath, const char* Database)
{
    // add log file
    ofstream LogFileOut;
    LogFileOut.open("LogInfo.txt");
    LogFileOut.close();

    // create temp file
    string tempDir = "./bpa_temp/";
    if ((_access(tempDir.c_str(), 0)) == -1)
    {
        _mkdir(tempDir.c_str());
    }
    else
    {
        remove(tempDir.c_str());
        _mkdir(tempDir.c_str());
    }

    BPA::BPAFilesIO::DatParse *data = new BPA::BPAFilesIO::DatParse();
    data->EraseAllDat();
    data->Parsing(FilePath);
    data->TrimBpaDat1();

    BPA::BPAFilesIO::GetInitConfigFromDb *read = new BPA::BPAFilesIO::GetInitConfigFromDb(Database);
    BPA::BPAFilesIO::Dat2Db dta(Database, data);
    dta.GetLineIrated();
    dta.PowerBaseChange();

    data->TrimBpaDat2();
    data->GetZoneProvinceID(Database);
    data->DatSumOutPut();

    dta.BpaDatSaveToDatBase();

    return STS_SUCCEED;
}

STS_MSG BPAMiniPowerFlow(const char* Database, int CaseID)
{
    BPA::BPAFilesIO::DatParse *datParser = new BPA::BPAFilesIO::DatParse();
    datParser->EraseAllDat();

    BPA::BPAFilesIO::Db2Dat dd;
    const char* outdat = "Tmp.dat";
    dd.DataBaseWriteToBpa(Database, outdat, CaseID);

    //数据拼接准备工作，重新解析和写入数据库
    datParser->Parsing("Tmp.dat");
    datParser->TrimBpaDat1();
    datParser->TrimBpaDat2();
    datParser->GetZoneProvinceID(Database);
    //覃老师需要的格式
    datParser->QinDatWriteBack();

    //此处执行覃老师的最小化潮流
    ToExecuteMinPf ExeMinPf(Database, CaseID);
    ExeMinPf.ExecuteMinPf();
    //残差分析
    MinPowerFlow minpf(Database, CaseID);
    minpf.MinPowerFlowResOrder();
    //潮流结果分区统计
    MinPowerInZone *qinminpf = new MinPowerInZone(Database, CaseID);
    qinminpf->ReleaseMinPfVector();
    qinminpf->MinPowerInZoneAchieve();

    return STS_SUCCEED;
}

STS_MSG BPABadDataCheck(const char* Database, int CaseID)
{
    // TODO: 逻辑需要修改
    BPA::BPAFilesIO::DatParse *datParser = new BPA::BPAFilesIO::DatParse();
    datParser->EraseAllDat();
    BPA::BPAFilesIO::Db2Dat dd;
    string outDat = "./bpa_temp/bad_data_check_temp.dat";
    dd.DataBaseWriteToBpa(Database, outDat.c_str(), CaseID);
    datParser->Parsing(outDat.c_str());
    datParser->TrimBpaDat1();
    datParser->TrimBpaDat2();
    datParser->GetZoneProvinceID(Database);

    //网络拓扑辨识模块
    int zonenum = 0, isolateBus = 0;
    CheckBpaConnAndBalan Checkout(datParser, Database, CaseID);
    Checkout.CheckBpaZoneConn(zonenum, isolateBus);
    Checkout.CheckWriteToDataBase();
    //节点和发电机检测模块
    BandBQcheck BandBQcheckout(datParser, Database, CaseID);
    BandBQcheckout.BandBQParCheck();
    BandBQcheckout.BadBus2Db();
    BandBQcheckout.BpaFindBadPowerFactor();
    //普通交流线路参数检测模块
    LineParCheck lpc(datParser, Database, CaseID);
    // TODO: 耗时过长，需要优化
    //BadLineCheckout.LittleSwitchHandle();//小开关支路的参数检测函数
    //lpc.FindLineInfComplet();
    lpc.FindLineLenghExist();
    lpc.BadLineparameterCheck();
    lpc.BadLineWriteToDatabase();
    //直流线路参数检测模块
    LineLDParCheck llpc(datParser, Database, CaseID);
    llpc.LineLdParCheck();
    llpc.LineLdPviMatch();
    llpc.LineLd2Db();

    //变压器参数检测模块
    TranParCheck tpc(datParser, Database, CaseID);
    //tpc.TranPar_2_Check();
    tpc.TransBadDataIdAllProgress();
    //tpc.Tran2Db();
    //不良数据写回模块
    ParCheckDb2Dat pcd(Database, CaseID);
    pcd.WriteToDat();
    //分区自动辨识
	ZoneAutoAdjustment test(Database, CaseID);
    test.ZoneBusGrid();
    test.ZoneChangeWriteDatabase();
    return STS_SUCCEED;
}

STS_MSG BPAUnbalanceCheck(const char* Database)
{
    BPA::BPAFilesIO::DatParse *data = new BPA::BPAFilesIO::DatParse();
    PowerBlance Power(data);
    Power.PowerBalanceInZone(Database);
    return STS_SUCCEED;
}

STS_MSG BPAFileWriteBack(const char* Database, const char* outdat, int CaseID)
{
    BPA::BPAFilesIO::Db2Dat dd;
    dd.DataBaseWriteToBpa(Database, outdat, CaseID);
    return STS_SUCCEED;
}

STS_MSG BPAToExecuteBpa(const char* DatFilePath)
{
    string pfntexe = "pfnt.exe";
    string datpath = "\"" + string(DatFilePath) + "\"";
    std::string command = pfntexe + " " + datpath;
    Process processpfnt(command);
    int exit_status = processpfnt.get_exit_status();
    cout << exit_status;

    return STS_SUCCEED;
}

STS_MSG BPADatPinJie_FindDifference(const char* Database)
{
    SqliteHelperDataBase db;
    SqliteHelperBuffer bufSQL;
    db.open(Database);

    //筛出该母线公共信息
    bufSQL.format("select * from PJ_UserChoose;");
    SqliteHelperTable Table_PJ_UserChoose = db.getTable(bufSQL);
    int nFile = Table_PJ_UserChoose.numRows();
    int *FileId = new int[nFile];
    for (int i = 0; i < nFile; i++)
    {
        Table_PJ_UserChoose.setRow(i);
        FileId[i] = Table_PJ_UserChoose.getIntField(0);
    }
    if (nFile > 1)
    {
        DatBridging pj;
        pj.FindDifference(Database, FileId, nFile);
    }
    return STS_SUCCEED;
}

STS_MSG BPADatPinJie_BpaDatWriteBack(const char* Database, const char* outdat)
{
    SqliteHelperDataBase db;
    SqliteHelperBuffer bufSQL;
    db.open(Database);

    //筛出该母线公共信息
    bufSQL.format(" select * from PJ_UserChoose;");
    SqliteHelperTable Table_PJ_UserChoose = db.getTable(bufSQL);

    if (Table_PJ_UserChoose.numRows() >= 2)
    {
        Table_PJ_UserChoose.setRow(0);
        int mainFileID = Table_PJ_UserChoose.getIntField(0);
        DatBridging pj;
        pj.DatWriteBack(Database, outdat, mainFileID);
    }
    return STS_SUCCEED;
}

